/**
 * @FILE:EmsPlvTypeManager.java
 * @AUTHOR:chenqiu
 * @DATE:2016年5月31日 下午2:38:31
 **/
package com.smarttest.common.util.protocol.ems;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.smarttest.common.beans.protolcol.Index;
import com.smarttest.common.beans.protolcol.SmartMessage;
import com.smarttest.common.beans.protolcol.plv.PlvConfig;
import com.smarttest.common.beans.protolcol.plv.PlvDefine.PlvType;
import com.smarttest.common.beans.protolcol.plv.PlvParser;
import com.smarttest.common.util.protocol.ByteUtil;
import com.smarttest.common.util.protocol.smart.SmartManager;
import com.smarttest.common.util.serializer.JsonSerializer;



/*******************************************
 * @COMPANY:北京汇通天下科技有限公司
 * @CLASS:EmsPlvTypeManager
 * @DESCRIPTION:
 * @AUTHOR:chenqiu
 * @VERSION:v1.0
 * @DATE:2016年5月31日 下午2:38:31
 *******************************************/
public abstract class EmsBaseParser {
	private PlvParser plvParser;
	private SmartManager smartManager;
	private Logger log = LoggerFactory.getLogger(this.getClass());
    public void parse0707(SmartMessage msg) {
    	try{
	        List<Map<String,Object>> result = new ArrayList<Map<String,Object>>(10);
	        Index index = new Index();
	        byte[] bodyData=msg.getData();
	        int count = ByteUtil.parseByte2Int(bodyData, index); // byte as count
	        Map<String,Object> currentRow = null;
	        List<String> boolkey=new ArrayList<String>();//记录布尔变量的名字
	        int j=0;
	        for (int i = 0; i < count; i++) {
	            int plvConfigId = ByteUtil.parseWord(bodyData, index); // id ->word
	            int length = ByteUtil.getLength(bodyData, index); // length-byte
	            if (plvConfigId == 0x000B) { // 标识是否为新记录
	            	currentRow = new HashMap<String,Object>();
	                result.add(currentRow);
	            	if(i>0){
	            		Map<String,Object> lastRow = result.get(j++);
	            		processBool(lastRow,currentRow,boolkey);
	            	}
	            }    
	            PlvConfig plvConfig=plvParser.getPlvConfig(plvConfigId);
//	            if(plvConfig!=null){
//	            	log.warn("没有找到配置ID："+plvConfigId);
//	            }
	            plvParser.parse(currentRow, bodyData, index,plvConfig,length);          
	            if(PlvType.BOOL==plvConfig.getType()){
	                String id=plvConfig.getId().substring(2).toUpperCase();
	            	String column="x"+id;
	            	boolkey.add(column);
	            }            
	        }
	        currentRow=null;
	        boolkey=null;
	        if(result.size()==0){
	        	result=null;
	        	log.warn("Smart-0x0707:解析没有数据。imei:{} ",msg.getImei());
	        	return;
	        }
	        for(Map<String,Object> distance: result){
	        	 distance.put("imei", msg.getImei());
	        	 Object obj=transferToObject(distance);
	        	 smartManager.insertEmsDistDetail(obj, msg.getImei());
	        }
	        log.info("Smart-0x0707:解析入MQ成功。Imei：{}",msg.getImei());
    	}catch(Exception ex){
    		log.error("Smart-0x0707-事件上报处理异常 , imei:{}", msg.getImei(),ex);
    		
    	}
    }
    
    /**
     * 对于BOOL 型的字段，为了节约流量，每次上报的单条命令里第1秒的数据是全的，其余秒的数据里的BOOL 
     * 量只有与上一次存在时的不同时才会存在，不存在的秒里面的状态与上一次存在时的状态相同。（BOOL量翻转上报）
     * @param lastRow,上一条记录	
     * @param currentRow，当前新纪录
     * @param boolKey，bool属性的字段
     */
    protected void processBool(Map<String, Object> lastRow,Map<String, Object> currentRow,List<String> boolKey){
    	for(int i=0;i<boolKey.size();i++){
    		String name=boolKey.get(i);
    		if(lastRow.containsKey(name)){
    			currentRow.put(name, lastRow.get(name));
    		}else{
    			log.info("没有找到key!");
    		}
    	}    	
    }    
    
    /**
     * 行程
     * @param session
     * @param msg
     */
    public void parse0704(SmartMessage msg) {
    	try{
    		Map<String, Object> distanceMap=this.parseTrip(msg.getData());
    		if(distanceMap==null){
    			log.warn("Smart-0x0704:解析没有数据。imei:{} ",msg.getImei());
    			return;
    		}
    		distanceMap.put("imei", msg.getImei());
    		Object obj=transferToObject(distanceMap);
    		smartManager.insertEmsDistance(obj, msg.getImei());
    		log.info("Smart-0x0704:解析入MQ成功。Imei：{}",msg.getImei());
    	}catch(Exception ex){
    		log.error("Smart-0x0704-事件上报处理异常 , imei:{}", msg.getImei(),ex);
    	}
    }
    protected Object transferToObject(Map<String, Object> map){
    	String str=JsonSerializer.toString(map);
		Object strObject=JsonSerializer.toObject(str, Object.class);
		return strObject;
    	
    }
    protected Object transferListToObject( List<Map<String,Object>> list){
    	String str=JsonSerializer.toString(list);
		Object strObject=JsonSerializer.toObject(str, Object.class);
		return strObject;
    	
    }
    
    /**
     * 行程占比
     * @param session
     * @param msg
     */
    public void parse0705(SmartMessage msg) {
        try{
        	Map<String, Object> distancePorpMap=this.parseTrip(msg.getData());
    		if(distancePorpMap==null){
    			log.warn("Smart-0x0705:解析没有数据。imei:{} ",msg.getImei());
    			return;
    		}
    		distancePorpMap.put("imei", msg.getImei());
    		Object obj=transferToObject(distancePorpMap);
    		smartManager.insertEmsDistanceProp(obj, msg.getImei());
    		log.info("Smart-0x0705:解析入MQ成功。Imei：{}",msg.getImei());
    	}catch(Exception ex){
    		log.error("Smart-0x0705-事件上报处理异常 , imei:{}", msg.getImei(),ex);
    	}
    }
    // 行程(0x0704)，行程占比(0x0705)解析
    protected Map<String, Object> parseTrip(byte[] bodyData){
    	if(bodyData==null){
    		return null;
    	}
        Map<String, Object> row = new HashMap<String, Object>();
        Index index = new Index();
        int count = ByteUtil.parseByte2Int(bodyData, index); // byte as count
        for (int i = 0; i < count; i++) {
            int plvConfigId = ByteUtil.parseWord(bodyData, index); // id ->word
            int length =ByteUtil.getLength(bodyData, index); // length-byte
            PlvConfig plvConfig=plvParser.getPlvConfig(plvConfigId);
             plvParser.parse(row, bodyData, index, plvConfig,length);
        }
        if(row.size()==0){
        	row=null;
        	return null;
        }
        return row;
    }
    
    /**
     * 0x0708 EMS故障码上报
     * @param session
     * @param msg
     */
    public void parse0708(SmartMessage msg) {
        try{
        	byte[] data=msg.getData();
        	Index index=new Index();
        	int PlvOrGNVcount=ByteUtil.parseByte(data, index);
        	if(PlvOrGNVcount==0){
        		log.info("Smart-0x0708 清除故障码报文。 imei:{} ",msg.getImei());
        	}
        	List<Map<String,Object>> result = new ArrayList<Map<String,Object>>(10);
        	Map<String, Object> plvRow = new HashMap<String, Object>();
        	for(int k=0;k<PlvOrGNVcount;k++){ 
        		int PlvOrGNVId=ByteUtil.parseWord(data, index);
	        	if(PlvOrGNVId==0xFF00){//解析时当发现ID为0xFF00时即为组ID；GNV结构
	        		int gnvCount=ByteUtil.parseByte(data, index);
	        		for(int i=0;i<gnvCount;i++){
	        			int plvCount=ByteUtil.parseByte(data, index);
	        			Map<String, Object> row = new HashMap<String, Object>();
	        			for(int j=0;j<plvCount;j++){
	        				 int plvConfigId = ByteUtil.parseWord(data, index); // id ->word
	        		         int length = ByteUtil.getLength(data, index);// length-byte	        		         
	        		         PlvConfig plvConfig=plvParser.getPlvConfig(plvConfigId);
	        		         plvParser.parse(row, data, index, plvConfig,length);
	        			}
	        			if(row.size()==0){
	        				log.warn("Smart-0x0708:此Struct其中的单个结果没有数据,{}",msg.getImei());
	    		         	row=null;
	    		         	continue;
	    		         }
	        			result.add(row);
	        		} 
	        	}else{
	        		 int plvConfigId = PlvOrGNVId; // id ->word
	        		 int length = ByteUtil.getLength(data, index); // length-byte
    		         PlvConfig plvConfig=plvParser.getPlvConfig(plvConfigId);
    		         plvParser.parse(plvRow, data, index, plvConfig,length);		
	        	}
        	}
        	
        	if(plvRow.size()>0){
        		result.add(plvRow);
        	}
             
        	if(result.size()==0&&PlvOrGNVcount!=0){
        		log.warn("Smart-0x0708:解析没有数据。imei:{} ",msg.getImei());
    			return;
    		}
        	Map<String, Object> addImei = new HashMap<String, Object>();
        	addImei.put("imei", msg.getImei());
        	addImei.put("codes", result);
        	Object obj=transferToObject(addImei);
        	
    		smartManager.insertEmsErrorCode(obj, msg.getImei());
    		log.info("Smart-0x0708:解析入MQ成功。Imei：{}",msg.getImei());
    		
    	}catch(Exception ex){
    		log.error("Smart-0x0708-事件上报处理异常 , imei:{}", msg.getImei(),ex);
    	}
    }    
    
    
    /**
     * 0x070A EMS分钟行程上报
     * @param session
     * @param msg
     */
    public void parse070A(SmartMessage msg) {
    	try{
    		Map<String, Object> distanceMinsMap=this.parseTrip(msg.getData());
    		if(distanceMinsMap==null){
    			log.warn("Smart-0x070A:解析没有数据。imei:{} ",msg.getImei());
    			return;
    		}
    		String distance=JsonSerializer.toString(distanceMinsMap);
    		smartManager.insertEmsMinsDistance(distance, msg.getImei());
    		log.info("Smart-0x070A:解析入MQ成功。Imei：{}",msg.getImei());
    	}catch(Exception ex){
    		log.error("Smart-0x070A-事件上报处理异常 , imei:{}", msg.getImei(),ex);
    	}
    }    

    public void setPlvParser(PlvParser plvParser) {
		this.plvParser = plvParser;
	}
    
    public void setSmartManager(SmartManager smartManager) {
        this.smartManager = smartManager;
    }
}
